//
//  smAppDelegate.m
//  shimaoHouse
//
//  Created by amy zhang on 12-6-27.
//  Copyright (c) 2012年 yst. All rights reserved.
//

#import "smAppDelegate.h"
#import "smViewController.h"

#import "smSearchListController.h"
#import "smHourseSearchController.h"
#import "smOrderSearchController.h"
#import "smContractSearchController.h"

#import "SUPApplication.h"
#import "SUPApplicationCallback.h"
#import "SUPRegistrationStatus.h"

#import "smMboSmMboDB.h"
#import "smMboCallbackHandler.h"
#import "SUPEngine.h"
#import "SUPDataVault.h"
#import "SUPConnectionProfile.h"
#import "smMboLocalKeyGenerator.h"

#define kSUP101DataVaultID @"SUP101DataVaultID"
#define kSUP101DataVaultSalt @"SUP101DataVaultSalt"

#define kSUP101ErrorBadPin -11111
#define kSUP101ErrorNoSettings -11112
#define kSUP101ErrorKeyNotAvailable -11113
#define kSUP101ErrorFailure -11114


@implementation smAppDelegate

@synthesize window = _window;
@synthesize navController = _navController;


@synthesize  connectStartTime, callbackHandler, firstrun, pin;

@synthesize passwordAlert, noTransportAlert;

@synthesize PINField, SUPPasswordField;

@synthesize SUPServerName, SUPServerPort, SUPUserName, SUPConnectionName, SUPPassword, SUPFarmID, SUPActivationCode, SUPManualRegistration;




smViewController *root;



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // Override point for customization after application launch
    
    //if(NO)
    if([self testForRequiredSettings])
    {
        
        // Register a callback handler. This should be done before any other SUP code is called.
        self.callbackHandler = [[smMboCallbackHandler new] autorelease];
        [smMboSmMboDB registerCallbackHandler:self.callbackHandler];
        
        // If messaging DB does not exist yet, we are running the app for the first time since installing it on the device
        self.firstrun = (![MessagingClientLib isMessagingDBExist]);
        
        [self showPasswordDialog];
        
        
    }
    
    // Create the main UI for the application. We will update it as we receive messages from the server.
    //[self.window addSubview:self.navController.view];
   // [self.window makeKeyAndVisible];
    
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    
    root = [[smViewController alloc] init];
    
    [self setupViewControllers];
    
    self.navController = [[UINavigationController alloc] initWithRootViewController:root]; 

    [self.window addSubview:self.navController.view];//self.navController.view];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    [root.navigationController.navigationBar setHidden:YES];
    
   
    return YES;
}
			

-(void)setupViewControllers
{
	UINavigationController* localNavCtroller;
	NSMutableArray* localViewCtrlArray =  [[NSMutableArray alloc] init];
	
	localNavCtroller = [self createNavControllerWrappingView:[smSearchListController class] tabIconName:@"toobarIcon_program.png" tabTitle:@"项目展示"];
	[localViewCtrlArray addObject:localNavCtroller];
	
	localNavCtroller = [self createNavControllerWrappingView:[smHourseSearchController class] tabIconName:@"toobarIcon_hourse.png" tabTitle:@"房源查询"];
	[localViewCtrlArray addObject:localNavCtroller];

    localNavCtroller = [self createNavControllerWrappingView:[smOrderSearchController class] tabIconName:@"toobarIcon_order.png" tabTitle:@"订单管理"];
	[localViewCtrlArray addObject:localNavCtroller];

    localNavCtroller = [self createNavControllerWrappingView:[smContractSearchController class] tabIconName:@"toobarIcon_contract.png" tabTitle:@"合同管理"];
	[localViewCtrlArray addObject:localNavCtroller];

//    
//	localNavCtroller = [self createNavControllerWrappingView:nil tabIconName:nil tabTitle:nil];
//	[localViewCtrlArray addObject:localNavCtroller];

    [root.navigationController.navigationBar setHidden:YES];
    
    
	root.viewControllers = localViewCtrlArray;
}


-(UINavigationController *)createNavControllerWrappingView:(Class)controller
											   tabIconName:(NSString*)iconName
												  tabTitle:(NSString*)tabTitle
{
	UIViewController* viewCtrller = [[controller alloc] init];
	UINavigationController* theNavCtrller = [[UINavigationController alloc] initWithRootViewController:viewCtrller];
	theNavCtrller.navigationBar.barStyle = UIBarStyleDefault;
	viewCtrller.tabBarItem.image = [UIImage imageNamed:iconName];
	viewCtrller.title = NSLocalizedString(tabTitle, @"");
    
	return theNavCtrller;
}

//- (void)applicationDidFinishLaunching:(UIApplication *)application 
//{
//    window = [[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];
//    [windowmakeKeyAndVisible];
//    tabBarController = [[CustomerTabBarControlleralloc] init];
//    [selfsetupViewControllers];
//    [windowaddSubview:tabBarController.view];
//}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    
    
    // In this example, because we delete and recreate the local database, we need to unsubscribe
    // and shut down the app when it is no longer active.  All data will be sent on next launch.
    [smMboSmMboDB unsubscribe];
    [SUPApplication stopConnection:0];
    exit(EXIT_SUCCESS);
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}



- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(actionSheet == self.noTransportAlert)
        exit (0);
    else
    {
        self.pin = [NSString stringWithString:self.PINField.text];
        if(self.firstrun)
            self.SUPPassword = [NSString stringWithString:self.SUPPasswordField.text];
        [self initializeSmMbo];
    }
}

- (id)init
{
    [super init];
    self.passwordAlert = nil;
    self.noTransportAlert = nil;
    return self;
}

- (void)showNoTransportAlert:(NSInteger) ret
{
    NSString *message = nil;
    
    if (ret == kSUP101ErrorNoSettings) {
        message = @"The connection settings have not been filled in for this application. Go to Settings, enter the connection information, and restart this app.";
    } else if (ret == kSUP101ErrorKeyNotAvailable) {
        message = @"Unable to access the key.";
    } else if (ret == kSUP101ErrorBadPin) {
        message = @"Incorrect PIN entered.";
    } else {
        message = @"An error occurred attempting to log in.";
    }
    
    self.noTransportAlert = [[UIAlertView alloc] initWithTitle:@"Unable to start message server" message:message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [self.noTransportAlert performSelectorOnMainThread:@selector(show) withObject:self waitUntilDone:YES];
    [self.noTransportAlert release];
}

- (void)showPasswordDialog
{
    NSString *message = nil;
    if(self.firstrun)
        message = @"Create a new PIN:";
    else
        message = @"Enter your PIN to unlock:";
    
    self.passwordAlert = [[UIAlertView alloc] initWithTitle:@"SUP101" 
                                                    message:@"\n\n\n\n"
                                                   delegate:self 
                                          cancelButtonTitle:NSLocalizedString(@"Cancel",nil) 
                                          otherButtonTitles:NSLocalizedString(@"OK",nil), nil];
    
    float y = 30;
    
    UILabel *PINFieldLabel = [[UILabel alloc] initWithFrame:CGRectMake(12,y,260,23)];
    PINFieldLabel.font = [UIFont systemFontOfSize:16];
    PINFieldLabel.textColor = [UIColor whiteColor];
    PINFieldLabel.backgroundColor = [UIColor clearColor];
    PINFieldLabel.shadowColor = [UIColor blackColor];
    PINFieldLabel.shadowOffset = CGSizeMake(0,-1);
    PINFieldLabel.textAlignment = UITextAlignmentCenter;
    PINFieldLabel.text = message;
    [passwordAlert addSubview:PINFieldLabel];
    
    y += 25;
    
    PINField = [[UITextField alloc] initWithFrame:CGRectMake(16,y,252,23)];
    PINField.font = [UIFont systemFontOfSize:16];
    PINField.backgroundColor = [UIColor whiteColor];
    PINField.secureTextEntry = YES;
    PINField.keyboardAppearance = UIKeyboardAppearanceAlert;
    
    [PINField becomeFirstResponder];
    [passwordAlert addSubview:PINField];
    
    UILabel *SUPPasswordFieldLabel;
    
    if(self.firstrun)
    {
        
        y += 25;
        
        SUPPasswordFieldLabel = [[UILabel alloc] initWithFrame:CGRectMake(12,y,260,23)];
        SUPPasswordFieldLabel.font = [UIFont systemFontOfSize:16];
        SUPPasswordFieldLabel.textColor = [UIColor whiteColor];
        SUPPasswordFieldLabel.backgroundColor = [UIColor clearColor];
        SUPPasswordFieldLabel.shadowColor = [UIColor blackColor];
        SUPPasswordFieldLabel.shadowOffset = CGSizeMake(0,-1);
        SUPPasswordFieldLabel.textAlignment = UITextAlignmentCenter;
        SUPPasswordFieldLabel.text = @"Enter your SUP password:";
        [passwordAlert addSubview:SUPPasswordFieldLabel];
        
        y += 25;
        
        SUPPasswordField = [[UITextField alloc] initWithFrame:CGRectMake(16,y,252,23)];
        SUPPasswordField.font = [UIFont systemFontOfSize:16];
        SUPPasswordField.backgroundColor = [UIColor whiteColor];
        SUPPasswordField.secureTextEntry = YES;
        SUPPasswordField.keyboardAppearance = UIKeyboardAppearanceAlert;
        
        //[SUPPasswordField becomeFirstResponder];
        [passwordAlert addSubview:SUPPasswordField];
        
        
    }
    [passwordAlert show];
    [passwordAlert release];
    [PINField release];
    [PINFieldLabel release];
    if(self.firstrun)
    {
        [SUPPasswordField release];
        [SUPPasswordFieldLabel release];
    }
}

- (BOOL)testForRequiredSettings
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    self.SUPServerName = [defaults stringForKey:@"supservername_preference"];
    MBOLogInfo(@"Server Name: %@", self.SUPServerName);
    self.SUPServerName=@"10.91.2.21";//61.164.42.174
    
    self.SUPServerPort = [defaults stringForKey:@"supserverport_preference"];
    if(self.SUPServerPort == nil)
        self.SUPServerPort = @"5001";
    
    self.SUPUserName = [defaults stringForKey:@"supusername_preference"];
    self.SUPUserName=@"supAdmin";
    self.SUPFarmID = [defaults stringForKey:@"supfarmid_preference"];
    if(self.SUPFarmID == nil)
        self.SUPFarmID = @"0";
    
    self.SUPManualRegistration = [defaults boolForKey:@"manualregistration_preference"];
    if(self.SUPManualRegistration)
    {
        self.SUPConnectionName = [defaults stringForKey:@"connectionname_preference"];
        self.SUPActivationCode = [defaults stringForKey:@"activationcode_preference"];
    }
    
    if(self.SUPServerName == nil ||
       self.SUPUserName == nil ||
       self.SUPFarmID == nil)
    {
        [self showNoTransportAlert:kSUP101ErrorNoSettings];
        return NO;
    }
    
    if(self.SUPManualRegistration && (self.SUPConnectionName == nil || self.SUPActivationCode == nil))
    {
        [self showNoTransportAlert:kSUP101ErrorNoSettings];
        return NO;        
    }
    
    return YES;
}



-(void)onConnectSuccess:(NSNotification *)obj
{
    // Connection to the server was made, so log in.
    // See [CallbackHandler onLoginSuccess] and [CallbackHandler onLoginFailure]. One of those
    // callbacks will be called at some point in the future.
    [[NSNotificationCenter defaultCenter] removeObserver:self name:ON_CONNECT_SUCCESS object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:ON_CONNECT_FAILURE object:nil];
    
    NSString *supuser = nil;
    NSString *suppass = nil;
    SUPDataVault *sup101vault = nil;
    @try {
        NSLog(@"Unlock SUP101 vault to get username/password credentials");
        sup101vault = [SUPDataVault getVault:kSUP101DataVaultID];
        [sup101vault unlock:self.pin withSalt:kSUP101DataVaultSalt];
        supuser = self.SUPUserName;
        suppass = [sup101vault getString:@"password"];
    }
    @catch (NSException *exception) {
        NSLog(@"Exception unlocking messaging data vault: %@: %@",[exception name],[exception reason]);
        [self showNoTransportAlert:kSUP101ErrorKeyNotAvailable];
    }
    @finally {
        [sup101vault lock];
    }
    
    if(self.firstrun)
    {
        NSLog(@"Running for the first time: check authentication credentials with the server");
        // Call beginOnlineLogin.  When the server responds that login is successful, the callback handler sends a notification,
        // and the Subscribe button is enabled.
        [smMboSmMboDB beginOnlineLogin:supuser password:suppass];
    }
    else
    {
        NSLog(@"Application was run before -- set authentication credentials, no need to check with server");
        // Set the credentials in the synchronization profile by calling offlineLogin
        
        [smMboSmMboDB offlineLogin:supuser password:suppass];
        
        // We send the same notification that onLoginSuccess callback handler method sends, so that the UI enables the Subscribe button
        NSNotification *n = [NSNotification notificationWithName:ON_LOGIN_SUCCESS object:nil];
        [[NSNotificationCenter defaultCenter] postNotification:n];
    }
}

-(void)onConnectFailure:(NSNotification *)obj
{
    // Once [SUPMessageClient start] is called, ON_CONNECT_FAILURE is sent from our callback handler
    // until the device is connected or something changes. If we haven't connected in 30 seconds, give up.
    NSDate *now = [NSDate date];
    if ([now timeIntervalSinceDate:self.connectStartTime] > 30) {
        [SUPApplication stopConnection:30];
        [self showNoTransportAlert:kSUP101ErrorFailure];
    }
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    
    // Override point for customization after application launch
    
    if([self testForRequiredSettings])
    {
        
        // Register a callback handler. This should be done before any other SUP code is called.
        self.callbackHandler = [[smMboCallbackHandler new] autorelease];
        [smMboSmMboDB registerCallbackHandler:self.callbackHandler];
        
        // If messaging DB does not exist yet, we are running the app for the first time since installing it on the device
        self.firstrun = (![MessagingClientLib isMessagingDBExist]);
        
        [self showPasswordDialog];
        
        
    }
    
    // Create the main UI for the application. We will update it as we receive messages from the server.
    [self.window addSubview:self.navController.view];
    [self.window makeKeyAndVisible];
    
    
    
}
- (void)initializeSmMbo
{
    // Set log level (optional -- this will generate a lot of output in the debug console)
    [MBOLogger setLogLevel:LOG_INFO];
    
    SUPDataVault *sup101vault = nil;
    SUPDataVault *messagingvault = nil;
    
    if(self.firstrun)
    {
        NSLog(@"Running the app for the first time.");
        
        
        
        // If the application is being run for the first time, we do the following:
        //      1. Remove the messaging data vault created by earlier versions of the application, if it exists.
        //      2. Remove the SUP101 data vault created by earlier versions of the application, if it exists.
        //      3. Create the messaging vault using the PIN as the password, leaving it unlocked for use by the messaging layer.
        //      4. Create the SUP101 data vault using the PIN as the password, and store the SUP username/password credentials 
        //                  and a database encryption key in the vault.
        //      
        @try
        {  
            NSLog(@"Delete preexisting messaging vault");
            [SUPDataVault deleteVault:kMessagingDataVaultID];
        }
        @catch(NSException *e)
        {  
            // Ignore any exception
        }
        @try {
            NSLog(@"Delete preexisting SUP101 data vault");
            [SUPDataVault deleteVault:kSUP101DataVaultID];
        }
        @catch(NSException *e)
        {  
            // Ignore any exception
        }
        
        @try {
            NSLog(@"Create new SUP101 data vault and store credentials and a generated encryption key");
            sup101vault = [SUPDataVault createVault:kSUP101DataVaultID withPassword:self.pin withSalt:kSUP101DataVaultSalt]; // creates the vault
            [sup101vault setString:@"password" withValue:self.SUPPassword];
            [sup101vault lock];
        }
        @catch (NSException *exception) {
            NSLog(@"Exception in creating new SUP101 data vault: %@: %@",[exception name], [exception reason]);
        }
        @try {
            NSLog(@"Create new messaging vault and leave it unlocked");
            messagingvault = [SUPDataVault createVault:kMessagingDataVaultID withPassword:self.pin withSalt:kDVStandardSalt];
        }
        @catch (NSException *exception) {
            NSLog(@"Exception in creating new messaging data vault: %@: %@",[exception name], [exception reason]);                
        }
        
    }
    else
    {
        // If the application has been run before, we get the PIN from the user, and use it to unlock the existing messaging data vault
        // (otherwise the messaging layer cannot start).
        //
        //
        NSLog(@"App has been run before.");
        @try {
            NSLog(@"Unlock messaging vault");
            messagingvault = [SUPDataVault getVault:kMessagingDataVaultID];
            [messagingvault unlock:self.pin withSalt:kDVStandardSalt];
        }
        @catch (NSException *exception) {
            NSLog(@"Exception unlocking messaging data vault: %@: %@",[exception name],[exception reason]);
            [self showNoTransportAlert:kSUP101ErrorBadPin];
        }
        
    }
    
    
    
    
    
    // Start up the messaging client. This will attempt to connect to the server. If a connection was
    // established we can proceed with login. See onConnectFailure: for more information about handling connection failure.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onConnectSuccess:) name:ON_CONNECT_SUCCESS object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onConnectFailure:) name:ON_CONNECT_FAILURE object:nil];
    self.connectStartTime = [NSDate date];
    SUPApplication* app = [SUPApplication getInstance];
    
    @try {
        sup101vault = [SUPDataVault getVault:kSUP101DataVaultID];
        [sup101vault unlock:self.pin withSalt:kSUP101DataVaultSalt];
        
        app.applicationIdentifier = @"smMbo";
        smMboCallbackHandler *ch = [smMboCallbackHandler getInstance];
        [ch retain];
        [app setApplicationCallback:ch];
        
        
        SUPConnectionProperties* props = app.connectionProperties;
        [props setServerName:self.SUPServerName];
        [props setPortNumber:[self.SUPServerPort intValue]];
        [props setUrlSuffix:@""];
        [props setFarmId:self.SUPFarmID];
        
        
        SUPLoginCredentials* login = [SUPLoginCredentials getInstance];
        if(self.SUPManualRegistration)
        {
            login.username = self.SUPConnectionName;
            login.password = nil;
            props.activationCode = self.SUPActivationCode;
        }
        else
        {
            login.username = self.SUPUserName;
            login.password = [sup101vault getString:@"password"];   
            props.activationCode = nil;
        }
        props.loginCredentials = login;
        
        [app registerApplication:30];
        
        // Normally you would not delete the local database. For this simple example, though,
        // deleting and creating an empty database will cause all data to be sent from the
        // server, and we can use [CallbackHandler onImportSuccess:] to know when to proceed.        
        [smMboSmMboDB deleteDatabase];
        [smMboSmMboDB createDatabase];
        SUPConnectionProfile *cp = [smMboSmMboDB getConnectionProfile];
        [cp.syncProfile setDomainName:@"default"];
        [cp enableTrace:NO];
        [cp.syncProfile enableTrace:YES];
        
        // Generate an encryption key for the database.
        [smMboSmMboDB generateEncryptionKey];
        [smMboSmMboDB closeConnection];
        // Store the encryption key in the data vault for future use.
        [sup101vault setString:@"encryptionkey" withValue:[cp getEncryptionKey]];
        
        // Since we are creating the database from scratch, we set the encryption key for the new database
        
        // If we were using the database from a previous run of the app and not creating it each time, an application should run the code below instead.
        // To successfully access a previously encrypted database, we set the key used by the connection profile.
        NSString *key = [sup101vault getString:@"encryptionkey"];
        NSLog(@"Got the encryption key: %@",key);
        [cp setEncryptionKey:key];
        [smMboSmMboDB closeConnection];
        
        [smMboSmMboDB setApplication:app];
        
        
        
        while([app registrationStatus] != SUPRegistrationStatus_REGISTERED)
        {
            [NSThread sleepForTimeInterval:1.0];
        }
        while([app connectionStatus] != SUPConnectionStatus_CONNECTED)
        {
            [NSThread sleepForTimeInterval:1.0];
        }
        
    }
    @catch (SUPPersistenceException * pe) {
        NSLog(@"%@: %@", [pe name],[pe message]);
        [self showNoTransportAlert:kSUP101ErrorFailure];
    }
    @finally 
    {
        [sup101vault lock];
    }
    
    
    
}
- (void)dealloc {
    self.navController = nil;
    self.window = nil;
    self.callbackHandler = nil;
    self.connectStartTime = nil;
    
    [super dealloc];
}



@end
